package com.yuyou.fn.timer.task;

import com.github.wens.mybatisplus.examples.Example;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander;
import com.xxl.job.core.log.XxlJobLogger;
import com.yuyou.fn.common.util.BigDecimals;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.settlement.constant.FeeCategoryEnum;
import com.yuyou.fn.settlement.constant.FeeShareStatus;
import com.yuyou.fn.settlement.constant.FeeStatus;
import com.yuyou.fn.settlement.constant.Subjects;
import com.yuyou.fn.settlement.entity.Fee;
import com.yuyou.fn.settlement.service.IChangeRecordService;
import com.yuyou.fn.settlement.service.IFeeService;
import com.yuyou.fn.settlement.service.ISettlementService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@JobHander(value="AdFeeShareTask")
@Component
public class AdFeeShareTask extends IJobHandler {

    @Resource
    private IFeeService feeService ;

    @Resource
    private ISettlementService settlementService ;

    @Resource
    private RedisTemplate<String,String> redisTemplate ;

    @Resource
    private IChangeRecordService changeRecordService;

    @Override
    public ReturnT<String> execute(String... params) throws Exception {

        Date currentDate  = DateUtils.addDays( TimeUtils.now(), 0 );

        //查找广告费
        Example<Fee> feeExample = Fee.createExample();
        feeExample.createCriteria().andEqualTo("feeCategoryId" , FeeCategoryEnum.AD_FEE.id )
                .andEqualTo("status" , FeeStatus.AUDITED.ordinal() )
                .andEqualTo("shareStatus" , FeeShareStatus.NOT_SHARE.ordinal() ).andLessThan("shareStart",currentDate);
        feeExample.orderBy("createTime");
        List<Fee> feeList = feeService.findListByExample(feeExample);

        boolean hasFail = false ;
        for(Fee fee : feeList ){

            if(StringUtils.isEmpty(fee.getShareMainAccountIds()) || fee.getShareStart() == null || fee.getShareEnd() == null ){
                XxlJobLogger.log("无法处理，信息不完整:{0}" , fee.getFeeId());
                continue;
            }

            try{
                handle(currentDate, fee);
            }catch (Exception e ){
                hasFail = true ;
                XxlJobLogger.log("处理失败:feeId={0},error={1}" , fee.getFeeId(),Utils.getExceptionStackTrace(e));
            }

        }

        return hasFail ?  ReturnT.FAIL : ReturnT.SUCCESS;
    }

    private void handle(Date currentDate, Fee fee) {
        int days =  TimeUtils.durationOfDay( fee.getShareStart(),fee.getShareEnd() );

        BigDecimal oneDayShareAmount = BigDecimals.calProportion(fee.getAmount(), BigDecimal.ONE,BigDecimal.valueOf(days));
        List<Long> accountIds = Utils.toLongIds( fee.getShareMainAccountIds() );
        BigDecimal eachOneShareAmount = BigDecimals.calProportion(oneDayShareAmount, BigDecimal.ONE,BigDecimal.valueOf(accountIds.size()));

        BigDecimal totalAmount=BigDecimal.ZERO;
        HashMap<Long,BigDecimal> map=new HashMap<Long,BigDecimal>();
        for (Long accountId : accountIds){
            BigDecimal amount = changeRecordService.sumBySubjectDirection(accountId, 0, Subjects.REAL_INCOME, TimeUtils.startOfDate(fee.getShareStart()), TimeUtils.endOfDate(fee.getShareEnd()));
            totalAmount=totalAmount.add(amount);
            map.put(accountId,amount);
        }

        int sharedDays =  Utils.parseInt( (String)redisTemplate.opsForHash().get("fee:share:day" , String.valueOf(fee.getFeeId()))) ;
        BigDecimal totalSharedAmount = BigDecimal.ZERO ;
        while (sharedDays < days ){
            Date date = DateUtils.addDays(fee.getShareStart() , sharedDays  );
            if(DateUtils.isSameDay(date, currentDate )){
                break;
            }
            String remark = "分摊【"+fee.getRemark()+"】-" + Utils.formatDate(date,"yyyy-MM-dd") ;


            for(Long accountId : accountIds ){
                BigDecimal tempAmount=eachOneShareAmount;
                if (totalAmount.doubleValue()>=0.01){
                    BigDecimal accountAmount=map.get(accountId);
                    if (accountAmount!=null){
                        tempAmount= BigDecimals.calProportion(oneDayShareAmount, accountAmount,totalAmount);
                    }
                }
                if (tempAmount.doubleValue()>=0.01){
                    settlementService.shareFee(accountId,fee.getFeeCategoryId(),fee.getReceiverMainAccountId(),tempAmount,remark,fee.getFeeId(),date);
                }
            }
            sharedDays++;
            totalSharedAmount = totalSharedAmount.add(oneDayShareAmount);
        }

        fee.setSharedAmount(fee.getSharedAmount().add(totalSharedAmount));
        if(sharedDays == days){
            fee.setShareStatus(FeeShareStatus.SHAREED.ordinal());
        }
        feeService.updateSelectiveById(fee);
        redisTemplate.opsForHash().put("fee:share:day" , String.valueOf(fee.getFeeId()),String.valueOf(sharedDays) );
    }


}
